# coding:utf-8
import getopt
import json
import sys
import requests
import os

global base_url  # 网站地址
global token  # 用户token 在个人中心处获得
global file_path  # 设置本地文档仓库位置
ExistsEocCount = 0
SonFolder = ''
folder = ''
tFileCopy = []
address = []
allAddress = []
idCount = []
wrongFile = []
cmdin = sys.argv


# 获取文档标题(暂时弃用)
def getFileTiitle(f1):
    with open(f1, encoding='utf-8') as f:
        try:
            firstLine = f.readlines()[0].rstrip()
        except:
            firstLine = '# TEST'
        return firstLine


# 过滤掉地址和后缀返回文档名称
def getUrlFileName(f):
    return os.path.basename(f).split('.')[0]


# 获取文档内容
def getFile(f):
    filen = ''

    try:
        with open(f, encoding='utf-8') as file_obj:
            for line in file_obj:
                filen += line

            return filen
    except FileNotFoundError:
        print('路径"{}"错误'.format(f))
        sys.exit(0)


# 子目录下文档查找
def addIsFile(docfile, tl, name, dir, id, existsEocCount):
    count = 0
    for docFileData in docfile['data']:
        if tl.split('.')[0].replace(" ", "") == docFileData['name']:
            count += 1
            existsEocCount += 1
            continue
    if count == 0:
        allAddress.append(dir + '\\' + name + "\\" + tl)
        idCount.append(id)
    return existsEocCount


# 获取指定Url文档夹下的所有文档
def getFileList(u):
    result = [f for f in os.listdir(u)
              if os.path.isfile(os.path.join(u, f))]
    return result


# 获取当前token用户现有文集
def getAnthology():
    url = base_url + '/api/get_projects/?token={}'.format(token)
    resp = requests.get(url=url)
    return resp.json()


# 获取网站文档的所有集合
def getDocList(pid):
    url = base_url + '/api/get_docs/?token={}'.format(token)
    data = {
        'pid': pid,
        'sort': 0
    }
    resp = requests.get(url=url, params=data)
    return resp.json()


def getDoc(did):
    url = base_url + '/api/get_doc/?token={}'.format(token)

    data = {
        'did': did,
    }

    resp = requests.get(url=url, params=data)
    return resp.json()


# 推送新的文档
def pushDoc(pid, title, doc):
    url = base_url + '/api/create_doc/?token={}'.format(token)
    data = {
        'pid': pid,
        'title': title.strip('#').rstrip().replace(" ", ""),
        'doc': doc
    }
    resp = requests.post(url=url, data=data)
    return resp.json()


# 更新文档
def setUpdate(pid, did, title, doc):
    url = base_url + '/api/modify_doc/?token={}'.format(token)

    data = {
        'pid': pid,
        'did': did,
        'title': title.strip('#').rstrip(),
        'doc': doc
    }
    resp = requests.post(url=url, data=data)
    return resp.json()


# 创建文集
def createAnthology(name, desc):
    url = base_url + '/api/create_project/?token={}'.format(token)

    data = {
        'name': name,
        'desc': desc,
        'role': 0
    }

    resp = requests.post(url=url, data=data)
    return resp.json()


# 检测文集是否创建 如果没有会自动创建
def testingAnthology():
    global tmp
    anthology = getAnthology()['data']
    localFolder = os.listdir(file_path)

    for i in localFolder:
        if os.path.isfile(file_path + "\\" + i):
            value = '仓库根目录下不允许存在文档！此文档目录无法有效获取！请将仓库根目录下文档移动至子目录！'
            print(f"\033[0;31m{value}\033[0m")
            print("仓库根目录下：" + file_path + " 有文档：" + i)
            print("请将文档放置在子目录下")
            print("地址：" + file_path + "\\" + i)
            sys.exit()
        tmp = False
        for j in anthology:
            if j['name'] == i:
                tmp = True
                break
            else:
                tmp = False

        if not tmp:
            status = createAnthology(i, '系统自动创建,请及时修改简介')['status']
            if status:
                print('已创建文集: "{}"'.format(i))


def push(news):
    # 获取文集
    if news: print("获取远程文集中")
    anthology = getAnthology()
    anthologyPidNameJson = {}
    anthologyNamePidJson = {}
    for data in anthology['data']:
        anthologyNamePidJson[data['name']] = data['id']
        anthologyPidNameJson[data['id']] = data['name']

    # 获取本地仓库文集列表
    if news: print("获取本地文集中")
    localAnyhologyNameJson = {}
    localDocNameLink = {}
    dir = os.listdir(file_path)
    for name in dir:
        link = file_path + '\\' + name
        if not os.path.isfile(link):
            dir1 = os.listdir(link)
            for name2 in dir1:
                if os.path.isfile(link + '\\' + name2) and name2.split('.')[1] == 'md':
                    localAnyhologyNameJson[name2.split('.')[0]] = name
                    localDocNameLink[name2.split('.')[0]] = link + '\\' + name2
                    continue
                else:
                    dir2 = os.listdir(link + '\\' + name2)
                    for name3 in dir2:
                        if os.path.isfile(link + '\\' + name2 + '\\' + name3) and name3.split('.')[1] == 'md':
                            localAnyhologyNameJson[''.join(name3.split()).split('.')[0]] = name
                            localDocNameLink[''.join(name3.split()).split('.')[0]] = link + '\\' + name2 + '\\' + name3
    # 获取远程文档和文集列表
    if news: print("正在对比")
    anyhologyNameJson = {}
    for data in anthologyPidNameJson:
        docJson = getDocList(data)
        for data1 in docJson['data']:
            anyhologyNameJson[''.join(data1['name'].split())] = anthologyPidNameJson[data]

    addJson = {}
    for name in localAnyhologyNameJson:
        if name not in anyhologyNameJson:
            addJson[name] = anthologyNamePidJson[localAnyhologyNameJson[name]]

    docCount = len(addJson)
    print("本地共有:{}篇文档 {}篇文档待推送".format(len(localDocNameLink), docCount))
    if docCount > 0:
        okCOunt = 0
        errCount = 0
        for data in addJson:
            print("正在推送:{}---{}".format(addJson[data], data))
            status = pushDoc(addJson[data], getUrlFileName(localDocNameLink[data]), getFile(localDocNameLink[data]))
            if status['status']:
                okCOunt += 1
            else:
                print("{}---{}推送失败 原因：{}".format(addJson[data], data, status))

        print("共:{}篇 成功:{}  失败{}".format(len(addJson), okCOunt, errCount))
        return True
    else:
        return False


# 更新文档
def update(arg):
    folder = arg.split('\\')
    home = file_path.split('\\')
    if len(folder) > len(folder):
        anthologyName = folder[len(folder)]
    else:
        anthologyName = folder[len(home)]

    folder2 = "".join(os.path.basename(arg).split())
    data = getAnthology()['data']
    pid = 0
    did = 0
    for i in data:
        if i['name'] == anthologyName:
            pid = i['id']

    data = getDocList(pid)['data']
    for j in data:
        if j['name'] + '.md' in folder2:
            did = j['id']

    result = setUpdate(pid, did, "".join(getUrlFileName(arg).split()), getFile(arg))
    if result['status']:
        print('更新文档: "{}" 成功'.format("".join(getUrlFileName(arg).split())))
    else:
        print('更新文档: "{}" 失败'.format("".join(getUrlFileName(arg).split())) + '-原因: {}'.format(result))


# 更新所有本地与远程有差异的文档
def updateAll(dir):
    print("正在进行更新前push操作")
    if not push(False):
        print("没有可上传文档")
    print("==================================")
    print("正在获取本地仓库中的文档")
    if len(dir) > 0:
        localDocLinkList = []

        dirList = os.listdir(dir)
        for data in dirList:
            if os.path.isfile(dir + '\\' + data) and data.split('.')[1] == 'md':
                localDocLinkList.append(dir + '\\' + data)
                continue
            dirList1 = os.listdir(dir + '\\' + data)
            for data1 in dirList1:
                if os.path.isfile(dir + '\\' + data + '\\' + data1) and data1.split('.')[1] == 'md':
                    localDocLinkList.append(dir + '\\' + data + '\\' + data1)
    else:
        firstLevelDir = os.listdir(file_path)
        dirList = []
        localDocLinkList = []
        # 获取本地文档仓库中的文集列表
        for dir in firstLevelDir:
            if os.path.isfile(file_path + '\\' + dir):
                continue
            dirList.append(dir)
        # 从本地文集列表中拿到所有文档的地址
        for docName in dirList:
            secondLevelDir = os.listdir(file_path + '\\' + docName)
            for docFileLink in secondLevelDir:
                if os.path.isfile(file_path + '\\' + docName + '\\' + docFileLink) and docFileLink.split(".")[
                    1] == 'md':
                    localDocLinkList.append(file_path + '\\' + docName + '\\' + docFileLink)
                    continue
                threeLevelDir = os.listdir(file_path + '\\' + docName + '\\' + docFileLink)
                for docFileLink1 in threeLevelDir:
                    if os.path.isfile(file_path + '\\' + docName + '\\' + docFileLink + '\\' + docFileLink1) and \
                            docFileLink1.split('.')[1] == 'md':
                        localDocLinkList.append(file_path + '\\' + docName + '\\' + docFileLink + '\\' + docFileLink1)
    cloudDidJson = {}
    # 将本地的文档名提取出来
    docNameList = []
    for name in localDocLinkList:
        tlist = name.split('\\')
        tlist = tlist[len(tlist) - 1].split('.')
        docNameList.append(tlist[0])
    # 吧文档名和对应的路径转换为json数据
    docNameJson = {}
    i = 0
    for add in docNameList:
        docNameJson[add] = localDocLinkList[i]
        i += 1
    # 通过传统的update方法更新
    # for link in docNameJson:
    #     update(docNameJson[link])
    # 过滤去重文集name列表
    newList = []
    for name in localDocLinkList:
        folder = name.split('\\')
        home = file_path.split('\\')
        if len(folder) > len(folder):
            anthologyName = folder[len(folder)]
        else:
            anthologyName = folder[len(home)]
        newList.append(anthologyName)
    newList = list(set(newList))
    print("正在获取远程文档信息")
    # 远程去获取文集id
    anthology = getAnthology()
    for data in anthology['data']:
        for name1 in newList:
            if data['name'] == name1:
                cloudDidJson[name1] = data['id']
                break
    # 拿一下远程所有文档的信息保存为json数据
    docJson = {}
    for wName in cloudDidJson:
        docJson[wName] = getDocList((cloudDidJson.get(wName)))
    print("正在获取本地文档内容")
    localdocNameDataJson = {}
    for localDocName in docNameJson:
        localdocNameDataJson[localDocName] = getFile(docNameJson[localDocName])
    print("差异比较中......")
    # 通过拿到的文档信息再拿一下文档的id和文档内容
    docNameDidJson = {}  # docName : Did
    docNamePidJson = {}  # docName : Pid
    anthologyPidNameJson = {}
    docNameDataJson = {}
    for data in docJson:
        for data1 in docJson[data]['data']:
            docNameDidJson["".join(data1['name'].split())] = data1['id']
            docNamePidJson["".join(data1['name'].split())] = cloudDidJson[data]
            anthologyPidNameJson[cloudDidJson[data]] = data
            docData = getDoc(data1['id'])['data']
            docNameDataJson[''.join(docData['name'].split())] = docData['md_content']

    updateDocNameJson = {}
    for docName in docNameJson:
        try:
            if localdocNameDataJson[docName] != docNameDataJson[''.join(docName.split())]:
                updateDocNameJson[docName] = docNameJson[docName]
        except KeyError:
            print('文档名有特殊字符或空格 请修改后上传  文档名=”{}“ '.format(docName))
    print("本地共有文档{} 有差异的文档:{}".format(len(localdocNameDataJson), len(updateDocNameJson)))
    if len(updateDocNameJson) > 0:
        okCount = 0
        ErrCount = 0
        for j in updateDocNameJson:
            pid = docNamePidJson["".join(j.split())]
            did = docNameDidJson["".join(j.split())]
            docName = getUrlFileName(updateDocNameJson[j])
            print("推送 '{}' : '{}' 中".format(anthologyPidNameJson[pid], j))
            result = setUpdate(pid, did, docName, getFile(updateDocNameJson[j]))
            if result['status']:
                okCount += 1
            else:
                ErrCount += 1
                print("文集 '{}' : '{}' 更新失败，原因{}".format(anthologyPidNameJson[pid], docName, result))
        print("==================================")
        print("推送完成 共:{}个差异  成功:{}个  失败:{}个".format(len(updateDocNameJson), okCount, ErrCount))


# 旧文档名字和新文档不一致的更新方法
def ifNameUpdate(oldName, newAddress):
    essayName = newAddress[0].split('\\')
    home = file_path.split('\\')
    if len(folder) > len(essayName):
        anthologyName = essayName[len(essayName)]
    else:
        anthologyName = essayName[len(home)]

    try:
        if oldName.split('.')[1] == 'md':
            oldName = oldName.split('.')[0]
    except Exception:
        pass

    data = getAnthology()['data']
    pid = 0
    did = 0
    for i in data:
        if i['name'] == anthologyName:
            pid = i['id']

    data = getDocList(pid)['data']
    for j in data:
        if j['name'] in oldName:
            did = j['id']

    tmpi = len(newAddress[0].split("\\"))
    result = setUpdate(pid, did, getUrlFileName(newAddress[0].split("\\")[tmpi - 1]), getFile(newAddress[0]))
    if result['status']:
        print('更新文档: 旧:"{}" ---->>'.format(oldName) + '新: "{}"   成功!'.format(newAddress[0].split("\\")[tmpi - 1]))
    else:
        print('更新文档: "{}" 失败'.format(oldName) + '-原因: {}'.format(result))
        print("可能是旧文档名不正确！")


def main(argv):
    global args
    try:
        opts, args = getopt.getopt(argv[1:], "hpau:s:", ["help", "push", "update=", "updates=", "updateall="])
    except Exception:
        opts = [('-h', '')]
        print("命令错误")
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            print('-选项后带: --选项后带= 代表有参数')
            print('-h | --help: 帮助')
            print('-p | --push:  doctools -p'
                  ' \n              将本地文档仓库内的文档全部推送')
            print('-u: | --update=:  doctools -u <Local address of documentation>'
                  ' \n              指定一个本地仓库内的文档地址，更新至网站')
            print('-s: | --updates=:  doctools -s <Old document name> <New document local address>'
                  ' \n              如果你的新文档与网页上的文档文档名不一致会无法更新 此命令第一个参数是旧文档名字 第二个参数是本地新文档地址')
            print('-a | --updateall=:  doctools -a '
                  ' \n              本地文档与远程文档进行差异比较，将有差异的文档更新'
                  ' \n              :  doctools --updateall <Specify a sub warehouse>'
                  ' \n              指定一个本地文档仓库的子目录(二级目录)与远程文档进行差异比较，将有差异的文档更新')
            sys.exit()
        elif opt in ("-p", "--push"):
            # 本地文件夹（文集）与平台文集做查找 没有就新增
            testingAnthology()
            if not push(True):
                print('没有任何新的文档，如需获取帮助可以-h 或 --help')

        elif opt in ("-u", "--update"):
            try:
                update(arg)
            except IndexError:
                print("参数错误")
                os.system('doctools -h')
        elif opt in ("-s", "--updates"):
            ifNameUpdate(arg, args)
        elif opt in ("-a", "--updateall"):
            testingAnthology()
            updateAll(arg)
        else:
            print("没有{}此选项".format(opt))


if __name__ == "__main__":
    env = os.environ.get("DOCTOOLS_HOME")
    if env is None:
        print("请在系统内配置脚本所在路径的环境变量：DOCTOOLS_HOME")
        sys.exit()
    try:
        with open('{}/config.json'.format(env), 'r', encoding='utf8') as fp:
            json_data = json.load(fp)
            base_url = json_data['base_url']
            token = json_data['token']
            file_path = json_data['file_path']
    except KeyError:
        print("json config file key is not exists")
        sys.exit(0)
    except FileNotFoundError:
        print("json config file is not exists")
        sys.exit(0)
    except:
        print("配置文件有误")
        sys.exit(0)

    if sys.argv[1] == '-h' or sys.argv[1] == '--help':
        main(sys.argv)
    elif len(file_path) == 0 or len(token) == 0 or len(base_url) == 0:
        print("首次使用脚本请在 {} 目录下的config.json内配置对应信息".format(env))
    else:
        # try:
        main(sys.argv)
        # except KeyboardInterrupt:
        #     print("程序被手动终止！")
        #     sys.exit(0)
        # except Exception as e:
        #     print('请检查您 的参数   如果有bug可将问题和报错信息复现发送至邮箱：2784404835@qq.com qq群：766160484')
